package serveur;


import java.awt.Point;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Random;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.StringTokenizer;

import time.Heure;

import map.Airport;
import map.PaintMap;
import core.Avion;
import core.ClasseVol;
import core.Graphe;
import core.Output;
import core.Ville;
import core.voyageur.Client;
import core.voyageur.Trajet;
import core.compagnie.CarteFidelite;
import core.compagnie.CompAerienne;
import core.compagnie.MetaCompagnie;
import core.compagnie.TypeCarteFidelite;
import core.dijkstra.DijkstraEngine;
import core.vols.PlanDeVol;
import core.vols.Vol;
import core.vols.VolCommercial;
import core.vols.VolInstance;
import exception.VolAnnuleException;
import exception.VolRetardeException;


public class SimulationServeur implements Simulation, Runnable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private Hashtable<String, Airport> aeroports;
	private ArrayList<Vol> vols;
	private Hashtable <Integer, VolInstance> volsInstance;
	private Hashtable <Integer, VolInstance> volsEnCours;
	private Hashtable<String, CompAerienne> compagnies;
	private Hashtable<String, Avion> avions;
	private Hashtable<String, Client> clients;
	private ArrayList<CarteFidelite> cartes;
	private ArrayList<TypeCarteFidelite> typesCartes;
	private ArrayList<Client> clientsSuivis;
	private Hashtable<String, Ville> villes = new Hashtable<String, Ville>();
	private Heure heureLocale;
	private PaintMap map;
	private boolean pause=false;
	private boolean running = false;
	private int scenario=0;

	public SimulationServeur() {
		super();
		vols = new ArrayList<Vol>();
		compagnies = new Hashtable<String, CompAerienne>();
		avions = new Hashtable<String, Avion>();
		aeroports = new Hashtable<String, Airport>();
		volsInstance = new Hashtable<Integer, VolInstance>();
		volsEnCours = new Hashtable<Integer, VolInstance>();
		clients = new Hashtable<String, Client>();
		cartes = new ArrayList<CarteFidelite>();
		typesCartes = new ArrayList<TypeCarteFidelite>();
		clientsSuivis = new ArrayList<Client>();
		initializeServeur(0);
	}
	
	public SimulationServeur(int scenario) {
		super();
		vols = new ArrayList<Vol>();
		compagnies = new Hashtable<String, CompAerienne>();
		avions = new Hashtable<String, Avion>();
		aeroports = new Hashtable<String, Airport>();
		volsInstance = new Hashtable<Integer, VolInstance>();
		volsEnCours = new Hashtable<Integer, VolInstance>();
		clients = new Hashtable<String, Client>();
		cartes = new ArrayList<CarteFidelite>();
		typesCartes = new ArrayList<TypeCarteFidelite>();
		clientsSuivis = new ArrayList<Client>();
		this.scenario=scenario;
	}
	
	public void initScenario1() {
		initializeServeur(1);
	}
	
	public void initScenario2() {
		initializeServeur(2);
	}
    
    private void updateHeureLocale(Heure tpsSup) {
    	heureLocale.addDuree(tpsSup);	
    }
	
    public void initAll(int i) {
    	
    	switch(i) {
    		case 1:
		    	try {
		    	CompAerienne c1 = compagnies.get("AE");
		    	CompAerienne c12 = compagnies.get("AF");
		    	
		    	
		    	Avion avion1 = new Avion(c12, "AE-327");
				Avion avion2 = new Avion(c1, "AF-654");
				Avion avion3 = new Avion(c1, "FO-782");
				ArrayList<VolInstance> volsAvion1 = new ArrayList<VolInstance>();
				ArrayList<VolInstance> volsAvion2 = new ArrayList<VolInstance>();
				ArrayList<VolInstance> volsAvion3 = new ArrayList<VolInstance>();	
				Vol v1 = getVol(aeroports.get("TLS"), aeroports.get("AA1"), new Heure(10));
				Vol v2 = getVol(aeroports.get("AA1"), aeroports.get("BA2"), new Heure(11));
				Vol v3 = getVol(aeroports.get("BA2"), aeroports.get("CA3"), new Heure(12));
				Vol v4 = getVol(aeroports.get("CA3"), aeroports.get("DA4"), new Heure(13));
				Vol v5 = getVol(aeroports.get("BA2"), aeroports.get("EA5"), new Heure(12));
				Vol v6 = getVol(aeroports.get("EA5"), aeroports.get("PAR"), new Heure(13));
				Vol v7 = getVol(aeroports.get("BA2"), aeroports.get("EA5"), new Heure(13));
				Vol v8 = getVol(aeroports.get("EA5"), aeroports.get("PAR"), new Heure(14));
								
				Date today = new Date();
				
				VolInstance vi1 = new VolInstance(v1, today, this, generateNumeroVolInstance(v1, new Heure(10), today), avion1);
				VolInstance vi2 = new VolInstance(v2, today, this, generateNumeroVolInstance(v2, new Heure(11), today), avion1);
				VolInstance vi3 = new VolInstance(v3, today, this, generateNumeroVolInstance(v3, new Heure(12), today), avion1);
				VolInstance vi4 = new VolInstance(v4, today, this, generateNumeroVolInstance(v4, new Heure(13), today), avion1);
				VolInstance vi5 = new VolInstance(v5, today, this, generateNumeroVolInstance(v5, new Heure(12), today), avion2);
				VolInstance vi6 = new VolInstance(v6, today, this, generateNumeroVolInstance(v6, new Heure(13), today), avion2);
				VolInstance vi7 = new VolInstance(v7, today, this, generateNumeroVolInstance(v7, new Heure(13), today), avion3);
				VolInstance vi8 = new VolInstance(v8, today, this, generateNumeroVolInstance(v8, new Heure(14), today), avion3);
				
				volsAvion1.add(vi1);
				volsAvion1.add(vi2);
				volsAvion1.add(vi3);
				volsAvion1.add(vi4);
				
				volsAvion2.add(vi5);
				volsAvion2.add(vi6);
				
				volsAvion3.add(vi7);
				volsAvion3.add(vi8);
		
				
				PlanDeVol pvAvion1 = new PlanDeVol(avion1, volsAvion1);
				PlanDeVol pvAvion2 = new PlanDeVol(avion1, volsAvion2);
				PlanDeVol pvAvion3 = new PlanDeVol(avion1, volsAvion3);
				
				avion1.setPlanDeVol(pvAvion1);
				avion2.setPlanDeVol(pvAvion2);
				avion3.setPlanDeVol(pvAvion3);
				
				c12.addAvion(avion1);
				c1.addAvion(avion2);
				c1.addAvion(avion3);
				
				volsInstance.put(vi1.getNumero(), vi1);
				volsInstance.put(vi2.getNumero(), vi2);
				volsInstance.put(vi3.getNumero(), vi3);
				volsInstance.put(vi4.getNumero(), vi4);
				volsInstance.put(vi5.getNumero(), vi5);
				volsInstance.put(vi6.getNumero(), vi6);
				volsInstance.put(vi7.getNumero(), vi7);
				volsInstance.put(vi8.getNumero(), vi8);
				
				/* vi5 est plein -> Mister X le rate */
				vi5.setPlein();
				
				ArrayList<VolInstance> listTrajet = new ArrayList<VolInstance>();
				listTrajet.add(vi1);
				listTrajet.add(vi2);
				listTrajet.add(vi5);
				listTrajet.add(vi6);
				Trajet trajet = new Trajet(listTrajet);
				Hashtable<VolInstance, ClasseVol> classes = new Hashtable<VolInstance, ClasseVol>();
				classes.put(vi1, ClasseVol.AFFAIRE);
				classes.put(vi2, ClasseVol.AFFAIRE);
				classes.put(vi5, ClasseVol.AFFAIRE);
				classes.put(vi6, ClasseVol.AFFAIRE);
				clients.get("X").acheterBillet(trajet, classes);
				
		    	} catch (Exception e) {
		    		e.printStackTrace();
		    	}
		    	break;
    		case 2:
    			try {   		    	
    		    	villes.put("TOULOUSE", new Ville(new Point(300, 470), "TOULOUSE"));
    		    	villes.put("PARIS", new Ville(new Point(310, 110), "PARIS"));
    		    	
    		    	    				
    		    	} catch (Exception e) {
    		    		e.printStackTrace();
    		    	}
    			break;
    		default:
    			break;
    	}
    }
    
    public ArrayList<Airport> getPlusProche(Ville v, int distance) {
    	Iterator<Airport> ita = aeroports.values().iterator();
    	ArrayList<Airport> res = new ArrayList<Airport>();
    	while(ita.hasNext()) {
    		Airport a = ita.next();
    		if(v.getP().distance(a.getCoord()) < distance) {
    			res.add(a);
    		}
    	}
    	return res;
    }
    
	
	/**
	 * @return the clientsSuivis
	 */
	public ArrayList<Client> getClientsSuivis() {
		return clientsSuivis;
	}

	public int generateNumeroVolInstance(Vol v, Heure h, Date d) {
		SimpleDateFormat format = new SimpleDateFormat("MMdd");
		String strDate = format.format(d);
		int num = Integer.valueOf(strDate);
		num = num*1000;
		num += Integer.parseInt(v.getCode().substring(2));
		num = (num+(h.getH()*100+h.getM())%999);
		return num;
	}
	
	/**
	 * @param AeroportA
	 * @param AeroportB
	 * @return codeVol
	 */
	
	public int generateCodeVol(Airport a, Airport b) { //Génération du code d'un Vol
		String aCode = a.getCode();
		String bCode = b.getCode();
		int aNum=0;
		int bNum=0;
		for(int i=0; i< aCode.length(); i++) {
			char cA = aCode.charAt(i);
			char cB = bCode.charAt(i);
			int asciiA = (int)cA;
			int asciiB = (int)cB;
			while(asciiA/10 != 0) asciiA = asciiA/10 + asciiA%10;
			while(asciiB/10 != 0) asciiB = asciiB/10 + asciiB%10;
			aNum += (10*(aCode.length()-i-1))*asciiA;
			bNum += (10*(bCode.length()-i-1))*asciiB;		
		}
		
		aNum = aNum*1000;
		int res = (aNum+bNum)*10;
		if(a.getCode().compareTo(b.getCode())>0) res +=1;
		return res;
	}
	
	public synchronized void launchFlights() { 
		
		if(scenario != 1) {
			Iterator<Vol> it = vols.iterator();
			while(it.hasNext()) {
				try {
				Vol volCourant = (Vol)it.next();
				Date today = new Date();
				int numVolI = generateNumeroVolInstance(volCourant, volCourant.getHeureDepart(), today);
				VolInstance volInstanceCourant;
				if(volCourant.getHeureDepart().equals(heureLocale)) {
					if(!volsInstance.containsKey(numVolI)) {
						volInstanceCourant = new VolInstance(volCourant, today, this, numVolI);
						volsInstance.put(numVolI, volInstanceCourant);
					} else volInstanceCourant = volsInstance.get(numVolI);
					
					volInstanceCourant.launch();
					volsEnCours.put(numVolI, volInstanceCourant);
				}
				} catch (VolRetardeException e) {
					Output.imprimer(e.getVol()+" retardé de "+e.getRetard());
					e.getVol().decalerVol(e.getRetard());
				} catch (VolAnnuleException e) {
					Output.imprimer(e.getVol()+" annulé");
					volsInstance.remove(e.getVol().getNumero());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} else {
			Iterator<VolInstance> itv = volsInstance.values().iterator();
			while(itv.hasNext()) {
				VolInstance volInstanceCourant = itv.next();
				if(volInstanceCourant.getHeureDepart().equals(heureLocale)) {								
					volInstanceCourant.launch();
					volsEnCours.put(volInstanceCourant.getNumero(), volInstanceCourant);
				}
				
			}
		}
		
	}
	
	public synchronized void flightStep() {
		Iterator<VolInstance> it = volsEnCours.values().iterator();
		while(it.hasNext()) {
			VolInstance v = it.next();
			if(v.isAterrit()) {
				volsInstance.remove(v.getNumero());
				it.remove();
			} else if(v.avance((int)(10*60)/9)) { //9 : 1km en 9s, 10*60, nombre de secondes simulées écoulées entre 2 appels de la fonction
				v.aterrissage();
			}
		}
	}
	
	public void initCompagnies(int i) {
		compagnies.clear();
		switch(i) {
		case 0:
			CompAerienne c = new CompAerienne("AirFrance", "AF", this);
			CompAerienne c2 = new CompAerienne("EasyJet", "EJ", this);
			CompAerienne c3 = new CompAerienne("XL Airways", "XA", this);
			try {
				addCompagnie(c);
				addCompagnie(c2);
				addCompagnie(c3);
				c.generateFlotte(15);
				c2.generateFlotte(15);
				c3.generateFlotte(15);
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
			break;
		case 1:
			CompAerienne c1 = new CompAerienne("AirFrance", "AF", this);
			CompAerienne c12 = new CompAerienne("AirElec", "AE", this);
			try {
				addCompagnie(c1);
				addCompagnie(c12);
								
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;
		case 2:

			try {
		    	CompAerienne c21 = new CompAerienne("C1", "C1", this);
		    	CompAerienne c22 = new CompAerienne("C2", "C2", this);
		    	CompAerienne c23 = new CompAerienne("C3", "C3", this);
		    	c21.generateFlotte(10);
		    	c22.generateFlotte(10);
		    	c23.generateFlotte(10);
	    	
		    	MetaCompagnie mc1 = new MetaCompagnie("MC12");
		    	mc1.addCompagnie(c21);	    	
		    	mc1.addCompagnie(c22);
		    	
				addCompagnie(c21);
				addCompagnie(c22);
				addCompagnie(c23);
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;
		default:
			break;
		}
	}

	
	private void initTypeCartes(int i) {
		Iterator<CompAerienne> itc = compagnies.values().iterator();
		while(itc.hasNext()) {
			CompAerienne c = itc.next();
			switch(i) {
			case 0:			
				TypeCarteFidelite t1 = new TypeCarteFidelite("Silver", c, 10);
				TypeCarteFidelite t2 = new TypeCarteFidelite("Gold", c, 20);
				TypeCarteFidelite t3 = new TypeCarteFidelite("Platinum", c, 30);
				typesCartes.add(t1);
				typesCartes.add(t2);
				typesCartes.add(t3);
				break;
			case 1:
				TypeCarteFidelite t4 = new TypeCarteFidelite("Tesla Club Membership", compagnies.get("AE"), 10);
				typesCartes.add(t4);
				break;
			case 2:
				TypeCarteFidelite t5 = new TypeCarteFidelite("C1 Premium", compagnies.get("C1"), 10);
				typesCartes.add(t5);
				break;
			default:
				break;
			}
		}
	}
	
	private void initClients(int i) {
		clients.clear();
		switch(i) {
		case 0:
			Client c = new Client("Buisson", "Antoine");
			c.addCarte(new CarteFidelite(c, typesCartes.get(0)));
			clients.put(c.getNom(), c); 
			c = new Client("Ramillien", "Rudy");
			c.addCarte(new CarteFidelite(c, typesCartes.get(1)));
			clients.put(c.getNom(), c);
			c = new Client("Jeandet", "Thibault");
			c.addCarte(new CarteFidelite(c, typesCartes.get(2)));
			clients.put(c.getNom(), c);
			break;
		case 1:
			Client x = new Client("X", "Mister");
			x.addCarte(new CarteFidelite(x, typesCartes.get(0)));
			clients.put(x.getNom(), x);
			clientsSuivis.add(x);
			break;
		case 2:
			Client m1 = new Client("M1", "Mister");
			m1.addCarte(new CarteFidelite(m1, typesCartes.get(0)));
			clients.put(m1.getNom(), m1);
			clientsSuivis.add(m1);
			break;
		default:
			break;
		}
	}
	
	public Vol getVol(Airport depart, Airport arrivee, Heure heureDepart) {
		for(Vol v : vols) {
			if(v.getDepart().equals(depart) && v.getArrivee().equals(arrivee) && v.getHeureDepart().equals(heureDepart)) return v;
		}
		return null;
	}
	
	public void addCompagnie(CompAerienne c) throws Exception {
		if(!compagnies.containsKey(c.getCode())) compagnies.put(c.getCode(), c);
		else throw new Exception("Code compagnie déjà présent");
	}
	
	private static Object randomValue(Hashtable<?, ?> table) {
        Object value = null;
        Collection<?> values = table.values();
        int numElements = values.size();
        int randomIndex = (int)(Math.random() * numElements);
        Iterator<?> iter = values.iterator();
        int index = 0;
        while (iter.hasNext()) {
              value = iter.next();
              if (index == randomIndex) {
                    return value;
              }
              index++;
        }
        return null;
  }
	
	public void createVolsFromAirports() {
		vols.clear();
		Airport depart;
		Airport voisin;
		Iterator<Airport> it = aeroports.values().iterator();
		while(it.hasNext()) { //Pour chaque aéroport
			depart=(Airport) it.next();
			Iterator<Airport> itVoisins = depart.getVoisins().iterator();
			while(itVoisins.hasNext()) { //Pour chaque voisin de cet aéroport
				int sel = 0;
				voisin = (Airport) itVoisins.next();
				Heure tpsVol = new Heure();
				int distance = (int) depart.getCoord().distance(voisin.getCoord());
				tpsVol.addSeconde(9*distance);
				CompAerienne randomComp = (CompAerienne)randomValue(compagnies);			
				String codeVol = randomComp.getCode() +  String.valueOf(generateCodeVol(depart, voisin));			
				for(int i=7;i<23;i+=1) {
					Heure heureDepart = new Heure(i);
					Vol newVol = new Vol(codeVol, depart, voisin, heureDepart, tpsVol, new VolCommercial());
					vols.add(newVol);
					randomComp.addVol(newVol);
					sel++;
				}
				
			}
		}
		Collections.sort(vols);
	}
	
	public void majNeighbours(ArrayList<String> airportsList) {
		if(!(aeroports.isEmpty())) {
			   /* ******Création de la list de list d'aeroports******* */
			    
					    //Pour chaque ligne de airportList
					    for(int i=0;i<airportsList.size();i++) {
					    	String neighbour;
					    	Airport current;
					    	StringTokenizer tk = new StringTokenizer(airportsList.get(i));
					    	current = aeroports.get(tk.nextElement());
					    	try {
					    		//On itère sur les composants String de la ligne (tous les voisins
					    		while(true) {
					    			neighbour=tk.nextToken();				    			
						    		current.addVoisins(aeroports.get(neighbour)); //on l'ajoute à neighbours
					    		}
					    	} catch(Exception e) {
					    		
					    	}
					    }
					} 
	}
	
	public ArrayList<Vol> getVolsFromAToB(Airport a, Airport b) {
		ArrayList<Vol> res = new ArrayList<Vol>();
		for(Vol v : vols) {
			if(v.getDepart().equals(a) && v.getArrivee().equals(b)) res.add(v);
		}
		return res;
	}
	
	/** Calcul du meilleur trajet entre 2 aeroports pour une date donnée 
	 * Utilisation de l'algorithme de Dijkstra pour calculer le plus court chemin entre 2 aeroports
	 * @param depart
	 * @param arrivee
	 * @param date
	 * @return res
	 * Renvoie une liste des Trajets possibles pour faire le voyage dep->arr à la date spécifiée
	 */	
	@Override
	public ArrayList<Trajet> calculateBestTrajet(Airport depart, Airport arrivee, Date date) {
		Graphe g = new Graphe(aeroports); //Graphe constitué par les aéroports, les arrêtes sont les voisins de chaque aéroport
		DijkstraEngine d = new DijkstraEngine(g);
		d.execute(depart, arrivee); // Calcul du plus court chemin de dep à arr
		Airport a = arrivee;
		ArrayList<Airport> chemin = new ArrayList<Airport>(); //Liste des aeroports pour atteindre arr depuis dep
		chemin.add(depart);
		try {
			while(!d.getPredecessor(a).equals(depart)) {
				chemin.add(1, d.getPredecessor(a));
				a=d.getPredecessor(a);
			}
		} catch (java.lang.NullPointerException e) {
			return new ArrayList<Trajet>();
		} catch (Exception e) {
			e.printStackTrace();
		}
		chemin.add(arrivee); 
		
		ArrayList<Trajet> res = new ArrayList<Trajet>();
		
		for(int i=0;i<chemin.size()-1;i++) { //Pour chaque couple de chemin
			Airport dep = chemin.get(i);
			Airport arr = chemin.get(i+1);
			ArrayList<Vol> volsCourants = getVolsFromAToB(dep, arr); //On récupère tous les Vols de dep vers arr
			for(int j=0;j<volsCourants.size();j++) { 
				//On récupère le numéro de vol et on crée le volInstance si il n'existe pas
				int numVolI = generateNumeroVolInstance(volsCourants.get(j), volsCourants.get(j).getHeureDepart(), date);
					try {
						if(!volsInstance.containsKey(numVolI)) volsInstance.put(numVolI, new VolInstance(volsCourants.get(j), date, this, numVolI));
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				/* Si c'est le premier tour de boucle de la première boucle for : on traite le vol depart->depart+1
				 * Dans ce cas on crée un nouveau Trajet dans la liste des trajets possibles
				 * Et on y ajoute le vol
				 */
				if(dep == depart) {
					res.add(new Trajet());
					res.get(j).addVol(volsInstance.get(numVolI));
				} else {
				/* Sinon on teste si l'heure de départ du vol actuel est compatible avec 
				 * l'heure d'arrivée du vol précédent
				 * Si oui on l'ajoute
				 */

					for(Trajet tCurrent : res) {
						VolInstance volPrecedent = tCurrent.getLastVol();
						Heure hLimiteDepart = new Heure(volPrecedent.getHeureDepart());
						hLimiteDepart.addDuree(volPrecedent.getDuree());
						hLimiteDepart.addMinute(30);
						Heure hDepCurrentVol = volsInstance.get(numVolI).getHeureDepart();
						if((hDepCurrentVol.compareTo(hLimiteDepart)>0) && (!volPrecedent.getDepart().equals(dep)) && (!volPrecedent.getArrivee().equals(arr))) {
							tCurrent.addVol(volsInstance.get(numVolI));
							break;
						}
					}
				}
								
			}
		}
		
		/*Il est possible que des trajets soit incorrects:
		 * En effet on pourrait avoir des trajets dont la destination n'est pas l'arrivée
		 * car il n'y avait plus de vol dans la journée pour finir le trajet
		 * On supprime ici ces vols
		 */
		Iterator<Trajet> ittrajet = res.iterator();
		while(ittrajet.hasNext()) {
			Trajet t = ittrajet.next();
			if (!t.getTrajet().get(t.getTrajet().size()-1).getArrivee().equals(arrivee)) ittrajet.remove();
		}
		return res;
	}
	
	@Override
	public Trajet calculateBestTrajet(Airport depart, Airport arrivee, Date date, Heure heure) {
		Graphe g = new Graphe(aeroports);
		DijkstraEngine d = new DijkstraEngine(g);
		d.execute(depart, arrivee);
		Airport a = arrivee;
		ArrayList<Airport> chemin = new ArrayList<Airport>();
		chemin.add(depart);
		while(!d.getPredecessor(a).equals(depart)) {
			chemin.add(1, d.getPredecessor(a));
			a=d.getPredecessor(a);
		}
		chemin.add(arrivee);
		Trajet t = new Trajet();
		return t;
	}
	

	
	public void initializeServeur(int i) { 
		volsInstance.clear();
		volsEnCours.clear();
		compagnies.clear();
		heureLocale = new Heure(9,50);
		pause = false;
		initCompagnies(i);
		initTypeCartes(i);
		initClients(i);
		if(i!=0) initAll(i);
	}
	
	/* Boucle principale du serveur */
	
	@Override
	public void run() {
		while (running) {
			try {
				Output.imprimer("Serveur : Il est " +heureLocale);
				launchFlights();
				flightStep();
				map.repaint();
				updateHeureLocale(new Heure(0,10));
				Thread.sleep(1250);	// dormir 'au plus' 1,25 secondes (difference temps execution et 1sec.)
				while(pause) Thread.sleep(1);
			} catch (Exception e) {e.printStackTrace();}
		}
	}

	public void pause() {
		pause=true;
		Output.imprimer("Serveur en pause...");
	}
	
	public void resume() {
		pause=false;
		Output.imprimer("Reprise du serveur...");
	}
	
	public boolean isPause() {
		return pause;
	}

	public void stop() {
		running = false;
		Output.imprimer("Arret du serveur...");
		initializeServeur(0);
	}

	public void setVols(ArrayList<Vol> vols) {
		this.vols = vols;
	}


	public void setAeroports(Hashtable<String, Airport> aeroports) {
		this.aeroports = aeroports;
	}
	
	
	public Hashtable<String, Airport> getAeroports() {
		return aeroports;
	}
	
	public void addAeroport(Airport a) {
		aeroports.put(a.getCode(), a);
	}
	
	public void clearAirports() {
		aeroports.clear();
	}

	public Heure getHeureLocale() {
		return heureLocale;
	}

	public Hashtable<Integer, VolInstance> getVolsEnCours() {
		return volsEnCours;
	}

	public void setMap(PaintMap map) {
		this.map = map;
	}

	public boolean isRunning() {
		return running;
	}

	public void setRunning(boolean running) {
		this.running = running;
	}

	public Hashtable<String, Client> getClients() {
		return clients;
	}
	
	public void addClient(Client c) {
		clients.put(c.getNom(), c);
	}

	public ArrayList<CarteFidelite> getCartes() {
		return cartes;
	}
	
	public void addCarte(CarteFidelite c) {
		cartes.add(c);
	}

	public ArrayList<TypeCarteFidelite> getTypesCartes() {
		return typesCartes;
	}
	
	public void addTypeCarteFidelite(TypeCarteFidelite t) {
		typesCartes.add(t);
	}
	
	public void addAvion(Avion a) {
		avions.put(a.getNom(), a);
	}

	public Hashtable<String, Avion> getAvions() {
		return avions;
	}

	public Hashtable<String, CompAerienne> getCompagnies() {
		return compagnies;
	}
	
	public Heure heureNextAterrissage() {
		Heure res = new Heure(23,55);
		Iterator<VolInstance> itv = volsEnCours.values().iterator();
		while(itv.hasNext()) {
			Heure hArrivee = new Heure(itv.next().getHeureArrivee());
			if(hArrivee.compareTo(res) < 0) res=hArrivee;
		}
		return res;
	}
	
	public VolInstance getVolSuivant(VolInstance v) {
		Collection<VolInstance> collecVols = volsInstance.values();
		ArrayList<VolInstance> listvols = new ArrayList<VolInstance>();
		listvols.addAll(collecVols);
		Collections.sort(listvols);
		Iterator<VolInstance> itv = listvols.iterator();
		while (itv.hasNext()) {
			VolInstance current = itv.next();
			if(current.getDepart().equals(v.getDepart()) && current.getArrivee().equals(v.getArrivee()) && current.getHeureDepart().compareTo(v.getHeureDepart()) > 0) {
				return current;
			}
		}
		return null;
	}

	/**
	 * @return the villes
	 */
	public Hashtable<String, Ville> getVilles() {
		return villes;
	}

	
}
